<?php
/**
 * 扩展工作流审批服务
 * 支持更多审批类型和自定义审批流程
 */

declare(strict_types=1);

namespace app\service;

use think\facade\Db;
use think\facade\Log;
use think\facade\Cache;

class ExtendedWorkflowService extends WorkflowService
{
    /**
     * 扩展的审批类型
     */
    public const EXTENDED_APPROVAL_TYPES = [
        // 原有审批类型
        'official_docs' => '公文审批',
        'seal' => '用章审批', 
        'contract' => '销售合同审批',
        'purchase' => '采购合同审批',
        'expense' => '报销审批',
        'invoice' => '发票审批',
        'ticket' => '收票审批',
        
        // 新增审批类型
        'leave' => '请假审批',
        'overtime' => '加班审批',
        'recruitment' => '招聘审批',
        'training' => '培训申请审批',
        'equipment' => '设备采购审批',
        'budget' => '预算申请审批',
        'promotion' => '职位晋升审批',
        'salary_adjustment' => '薪资调整审批',
        'transfer' => '调岗申请审批',
        'resignation' => '离职审批',
        'business_trip' => '出差申请审批',
        'meeting_room' => '会议室预约审批',
        'vehicle' => '车辆使用审批',
        'office_supplies' => '办公用品申请审批',
        'marketing_activity' => '营销活动审批',
        'system_change' => '系统变更审批',
        'data_access' => '数据访问权限审批',
        'third_party_service' => '第三方服务审批'
    ];

    /**
     * 审批流程模板
     */
    public const WORKFLOW_TEMPLATES = [
        'simple' => [
            'name' => '简单流程',
            'description' => '单级审批，适用于金额较小或影响较小的申请',
            'steps' => 1,
            'roles' => ['direct_supervisor']
        ],
        'standard' => [
            'name' => '标准流程', 
            'description' => '双级审批，适用于一般性申请',
            'steps' => 2,
            'roles' => ['direct_supervisor', 'department_manager']
        ],
        'complex' => [
            'name' => '复杂流程',
            'description' => '三级审批，适用于重要申请',
            'steps' => 3,
            'roles' => ['direct_supervisor', 'department_manager', 'general_manager']
        ],
        'financial' => [
            'name' => '财务流程',
            'description' => '财务相关审批流程',
            'steps' => 3,
            'roles' => ['direct_supervisor', 'financial_manager', 'general_manager']
        ],
        'hr' => [
            'name' => '人事流程',
            'description' => '人事相关审批流程',
            'steps' => 3,
            'roles' => ['direct_supervisor', 'hr_manager', 'general_manager']
        ],
        'it' => [
            'name' => 'IT流程',
            'description' => '信息技术相关审批流程',
            'steps' => 2,
            'roles' => ['it_manager', 'general_manager']
        ]
    ];

    /**
     * 审批条件配置
     */
    public const APPROVAL_CONDITIONS = [
        'amount_based' => [
            'description' => '基于金额的条件审批',
            'rules' => [
                ['min' => 0, 'max' => 1000, 'template' => 'simple'],
                ['min' => 1001, 'max' => 10000, 'template' => 'standard'],
                ['min' => 10001, 'max' => 50000, 'template' => 'complex'],
                ['min' => 50001, 'max' => null, 'template' => 'financial']
            ]
        ],
        'department_based' => [
            'description' => '基于部门的条件审批',
            'rules' => [
                'finance' => 'financial',
                'hr' => 'hr',
                'it' => 'it',
                'default' => 'standard'
            ]
        ],
        'urgency_based' => [
            'description' => '基于紧急程度的条件审批',
            'rules' => [
                'urgent' => 'simple',
                'normal' => 'standard',
                'low' => 'complex'
            ]
        ]
    ];

    /**
     * 创建自定义审批流程
     */
    public function createCustomWorkflow(array $config): int
    {
        Db::startTrans();
        try {
            // 验证配置
            $this->validateWorkflowConfig($config);
            
            // 创建工作流模板
            $templateData = [
                'name' => $config['name'],
                'description' => $config['description'] ?? '',
                'type' => $config['type'],
                'template_code' => $config['template_code'] ?? 'custom_' . time(),
                'conditions' => json_encode($config['conditions'] ?? [], JSON_UNESCAPED_UNICODE),
                'steps_config' => json_encode($config['steps'], JSON_UNESCAPED_UNICODE),
                'status' => 1,
                'create_time' => time(),
                'update_time' => time()
            ];
            
            $templateId = Db::name('workflow_template')->insertGetId($templateData);
            
            // 创建审批步骤配置
            foreach ($config['steps'] as $index => $step) {
                $stepData = [
                    'template_id' => $templateId,
                    'step_number' => $index + 1,
                    'step_name' => $step['name'],
                    'step_type' => $step['type'] ?? 'approval',
                    'approver_type' => $step['approver_type'], // role, user, department
                    'approver_config' => json_encode($step['approver_config'], JSON_UNESCAPED_UNICODE),
                    'conditions' => json_encode($step['conditions'] ?? [], JSON_UNESCAPED_UNICODE),
                    'is_required' => $step['is_required'] ?? 1,
                    'timeout_hours' => $step['timeout_hours'] ?? 24,
                    'create_time' => time()
                ];
                
                Db::name('workflow_template_step')->insert($stepData);
            }
            
            Db::commit();
            
            // 清理模板缓存
            Cache::delete('workflow:templates');
            
            Log::info('创建自定义工作流模板成功', ['template_id' => $templateId, 'name' => $config['name']]);
            
            return $templateId;
            
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }

    /**
     * 根据条件自动选择审批流程
     */
    public function getApprovalFlowByConditions(string $type, array $context): array
    {
        // 获取审批类型的配置
        $typeConfig = $this->getApprovalTypeConfig($type);
        if (!$typeConfig) {
            throw new \Exception("未找到审批类型配置: $type");
        }

        // 根据条件选择流程模板
        $templateCode = $this->selectTemplateByConditions($typeConfig, $context);
        
        // 获取流程模板
        $template = $this->getWorkflowTemplate($templateCode);
        if (!$template) {
            throw new \Exception("未找到工作流模板: $templateCode");
        }

        // 解析审批人
        $approvers = $this->resolveApprovers($template, $context);
        
        return [
            'template' => $template,
            'approvers' => $approvers,
            'estimated_duration' => $this->estimateApprovalDuration($template)
        ];
    }

    /**
     * 创建条件化审批流程
     */
    public function createConditionalApproval(string $type, int $businessId, int $applicantId, array $context): int
    {
        // 获取适合的审批流程
        $flow = $this->getApprovalFlowByConditions($type, $context);
        
        // 创建审批记录
        return $this->createApprovalWithTemplate($type, $businessId, $applicantId, $flow, $context);
    }

    /**
     * 批量审批操作
     */
    public function batchApprovalOperation(int $approverId, array $operations): array
    {
        $results = [];
        $successCount = 0;
        $failureCount = 0;
        
        Db::startTrans();
        try {
            foreach ($operations as $operation) {
                try {
                    $result = $this->processApproval(
                        $operation['approval_id'],
                        $approverId,
                        $operation['action'],
                        $operation['remark'] ?? ''
                    );
                    
                    $results[] = [
                        'approval_id' => $operation['approval_id'],
                        'success' => true,
                        'message' => '处理成功'
                    ];
                    $successCount++;
                    
                } catch (\Exception $e) {
                    $results[] = [
                        'approval_id' => $operation['approval_id'],
                        'success' => false,
                        'message' => $e->getMessage()
                    ];
                    $failureCount++;
                }
            }
            
            Db::commit();
            
            Log::info('批量审批操作完成', [
                'approver_id' => $approverId,
                'total' => count($operations),
                'success' => $successCount,
                'failure' => $failureCount
            ]);
            
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
        
        return [
            'total' => count($operations),
            'success_count' => $successCount,
            'failure_count' => $failureCount,
            'results' => $results
        ];
    }

    /**
     * 审批流程转办
     */
    public function transferApproval(int $approvalId, int $fromUserId, int $toUserId, string $reason): bool
    {
        Db::startTrans();
        try {
            // 验证转办权限
            if (!$this->canTransferApproval($approvalId, $fromUserId)) {
                throw new \Exception('无权限转办此审批');
            }
            
            // 更新当前审批步骤的审批人
            $updated = Db::name('workflow_approval_step')
                ->where('approval_id', $approvalId)
                ->where('approver_id', $fromUserId)
                ->where('status', self::STATUS['PENDING'])
                ->update([
                    'approver_id' => $toUserId,
                    'transfer_from' => $fromUserId,
                    'transfer_reason' => $reason,
                    'transfer_time' => time(),
                    'update_time' => time()
                ]);
            
            if (!$updated) {
                throw new \Exception('审批转办失败，可能审批已处理或不存在');
            }
            
            // 记录转办历史
            Db::name('workflow_approval_history')->insert([
                'approval_id' => $approvalId,
                'approver_id' => $fromUserId,
                'action' => 'transfer',
                'remark' => "转办给用户ID: $toUserId, 原因: $reason",
                'create_time' => time()
            ]);
            
            Db::commit();
            
            // 发送转办通知
            $this->sendTransferNotification($approvalId, $fromUserId, $toUserId, $reason);
            
            return true;
            
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }

    /**
     * 审批流程撤回
     */
    public function withdrawApproval(int $approvalId, int $applicantId, string $reason): bool
    {
        Db::startTrans();
        try {
            $approval = Db::name('workflow_approval')->where('id', $approvalId)->find();
            if (!$approval) {
                throw new \Exception('审批记录不存在');
            }
            
            if ($approval['applicant_id'] != $applicantId) {
                throw new \Exception('只能撤回自己的申请');
            }
            
            if (!in_array($approval['status'], [self::STATUS['PENDING'], self::STATUS['PROCESSING']])) {
                throw new \Exception('只能撤回待审批或审批中的申请');
            }
            
            // 更新审批状态
            Db::name('workflow_approval')
                ->where('id', $approvalId)
                ->update([
                    'status' => self::STATUS['CANCELLED'],
                    'withdraw_reason' => $reason,
                    'withdraw_time' => time(),
                    'update_time' => time()
                ]);
            
            // 取消所有待处理的审批步骤
            Db::name('workflow_approval_step')
                ->where('approval_id', $approvalId)
                ->where('status', self::STATUS['PENDING'])
                ->update([
                    'status' => self::STATUS['CANCELLED'],
                    'update_time' => time()
                ]);
            
            // 记录撤回历史
            Db::name('workflow_approval_history')->insert([
                'approval_id' => $approvalId,
                'approver_id' => $applicantId,
                'action' => 'withdraw',
                'remark' => "申请人撤回申请，原因: $reason",
                'create_time' => time()
            ]);
            
            // 更新业务表状态
            $this->updateBusinessApprovalStatus($approval['type'], $approval['business_id'], self::STATUS['CANCELLED']);
            
            Db::commit();
            
            // 发送撤回通知
            $this->sendWithdrawNotification($approvalId, $reason);
            
            return true;
            
        } catch (\Exception $e) {
            Db::rollback();
            throw $e;
        }
    }

    /**
     * 获取审批统计数据
     */
    public function getExtendedApprovalStatistics(int $userId, array $options = []): array
    {
        $timeRange = $options['time_range'] ?? 'month'; // week, month, quarter, year
        $groupBy = $options['group_by'] ?? 'type'; // type, status, department
        
        $timeCondition = $this->buildTimeCondition($timeRange);
        
        $stats = [];
        
        // 按类型统计
        if ($groupBy === 'type' || $groupBy === 'all') {
            $typeStats = Db::name('workflow_approval_step')
                ->alias('s')
                ->join('workflow_approval a', 's.approval_id = a.id')
                ->field('a.type, COUNT(*) as total, 
                        SUM(CASE WHEN s.status = 0 THEN 1 ELSE 0 END) as pending,
                        SUM(CASE WHEN s.status = 2 THEN 1 ELSE 0 END) as approved,
                        SUM(CASE WHEN s.status = 3 THEN 1 ELSE 0 END) as rejected')
                ->where('s.approver_id', $userId)
                ->where($timeCondition)
                ->group('a.type')
                ->select()
                ->toArray();
            
            $stats['by_type'] = $typeStats;
        }
        
        // 按状态统计
        if ($groupBy === 'status' || $groupBy === 'all') {
            $statusStats = Db::name('workflow_approval_step')
                ->alias('s')
                ->join('workflow_approval a', 's.approval_id = a.id')
                ->field('s.status, COUNT(*) as count')
                ->where('s.approver_id', $userId)
                ->where($timeCondition)
                ->group('s.status')
                ->select()
                ->toArray();
            
            $stats['by_status'] = $statusStats;
        }
        
        // 审批效率统计
        $efficiencyStats = $this->getApprovalEfficiencyStats($userId, $timeCondition);
        $stats['efficiency'] = $efficiencyStats;
        
        return $stats;
    }

    /**
     * 验证工作流配置
     */
    private function validateWorkflowConfig(array $config): void
    {
        $required = ['name', 'type', 'steps'];
        foreach ($required as $field) {
            if (!isset($config[$field])) {
                throw new \Exception("工作流配置缺少必填字段: $field");
            }
        }
        
        if (empty($config['steps']) || !is_array($config['steps'])) {
            throw new \Exception('工作流步骤配置不能为空');
        }
        
        foreach ($config['steps'] as $index => $step) {
            if (!isset($step['name']) || !isset($step['approver_type'])) {
                throw new \Exception("步骤 $index 配置不完整");
            }
        }
    }

    /**
     * 获取审批类型配置
     */
    private function getApprovalTypeConfig(string $type): ?array
    {
        $cacheKey = "workflow:type_config:$type";
        $cached = Cache::get($cacheKey);
        if ($cached !== null) {
            return $cached;
        }
        
        $config = Db::name('workflow_type_config')->where('type', $type)->find();
        if ($config) {
            $config['conditions'] = json_decode($config['conditions'], true);
            Cache::set($cacheKey, $config, 3600);
        }
        
        return $config;
    }

    /**
     * 根据条件选择模板
     */
    private function selectTemplateByConditions(array $typeConfig, array $context): string
    {
        $conditions = $typeConfig['conditions'] ?? [];
        
        // 金额条件
        if (isset($context['amount']) && isset($conditions['amount_rules'])) {
            foreach ($conditions['amount_rules'] as $rule) {
                if ($context['amount'] >= $rule['min'] && 
                    ($rule['max'] === null || $context['amount'] <= $rule['max'])) {
                    return $rule['template'];
                }
            }
        }
        
        // 部门条件
        if (isset($context['department']) && isset($conditions['department_rules'])) {
            return $conditions['department_rules'][$context['department']] ?? 
                   $conditions['department_rules']['default'] ?? 'standard';
        }
        
        // 紧急程度条件
        if (isset($context['urgency']) && isset($conditions['urgency_rules'])) {
            return $conditions['urgency_rules'][$context['urgency']] ?? 'standard';
        }
        
        return $typeConfig['default_template'] ?? 'standard';
    }

    /**
     * 获取工作流模板
     */
    private function getWorkflowTemplate(string $templateCode): ?array
    {
        $cacheKey = "workflow:template:$templateCode";
        $cached = Cache::get($cacheKey);
        if ($cached !== null) {
            return $cached;
        }
        
        $template = Db::name('workflow_template')
            ->where('template_code', $templateCode)
            ->where('status', 1)
            ->find();
        
        if ($template) {
            $steps = Db::name('workflow_template_step')
                ->where('template_id', $template['id'])
                ->order('step_number', 'asc')
                ->select()
                ->toArray();
            
            $template['steps'] = $steps;
            Cache::set($cacheKey, $template, 3600);
        }
        
        return $template;
    }

    /**
     * 解析审批人
     */
    private function resolveApprovers(array $template, array $context): array
    {
        $approvers = [];
        
        foreach ($template['steps'] as $step) {
            $stepApprovers = [];
            
            switch ($step['approver_type']) {
                case 'role':
                    $stepApprovers = $this->getApproversByRole($step['approver_config'], $context);
                    break;
                case 'user':
                    $stepApprovers = $this->getApproversByUser($step['approver_config']);
                    break;
                case 'department':
                    $stepApprovers = $this->getApproversByDepartment($step['approver_config'], $context);
                    break;
            }
            
            $approvers[] = [
                'step_number' => $step['step_number'],
                'step_name' => $step['step_name'],
                'approvers' => $stepApprovers,
                'is_required' => $step['is_required']
            ];
        }
        
        return $approvers;
    }

    /**
     * 根据角色获取审批人
     */
    private function getApproversByRole(array $config, array $context): array
    {
        // 简化实现，实际应该根据角色配置查询用户
        return [1]; // 返回管理员ID
    }

    /**
     * 根据用户ID获取审批人
     */
    private function getApproversByUser(array $config): array
    {
        return $config['user_ids'] ?? [];
    }

    /**
     * 根据部门获取审批人
     */
    private function getApproversByDepartment(array $config, array $context): array
    {
        // 简化实现，实际应该根据部门配置查询用户
        return [1]; // 返回部门主管ID
    }

    /**
     * 估算审批时长
     */
    private function estimateApprovalDuration(array $template): int
    {
        $totalHours = 0;
        foreach ($template['steps'] as $step) {
            $totalHours += $step['timeout_hours'] ?? 24;
        }
        return $totalHours;
    }

    /**
     * 使用模板创建审批
     */
    private function createApprovalWithTemplate(string $type, int $businessId, int $applicantId, array $flow, array $context): int
    {
        // 提取所有审批人
        $allApprovers = [];
        foreach ($flow['approvers'] as $step) {
            $allApprovers = array_merge($allApprovers, $step['approvers']);
        }
        
        // 调用父类方法创建审批
        return $this->createApproval(
            $type,
            $businessId,
            $applicantId,
            $allApprovers,
            $context['title'] ?? "审批申请",
            $context
        );
    }

    /**
     * 检查是否可以转办
     */
    private function canTransferApproval(int $approvalId, int $userId): bool
    {
        return Db::name('workflow_approval_step')
            ->where('approval_id', $approvalId)
            ->where('approver_id', $userId)
            ->where('status', self::STATUS['PENDING'])
            ->count() > 0;
    }

    /**
     * 发送转办通知
     */
    private function sendTransferNotification(int $approvalId, int $fromUserId, int $toUserId, string $reason): void
    {
        Log::info('审批转办通知', [
            'approval_id' => $approvalId,
            'from_user' => $fromUserId,
            'to_user' => $toUserId,
            'reason' => $reason
        ]);
    }

    /**
     * 发送撤回通知
     */
    private function sendWithdrawNotification(int $approvalId, string $reason): void
    {
        Log::info('审批撤回通知', [
            'approval_id' => $approvalId,
            'reason' => $reason
        ]);
    }

    /**
     * 构建时间条件
     */
    private function buildTimeCondition(string $timeRange): array
    {
        $now = time();
        switch ($timeRange) {
            case 'week':
                $start = $now - 7 * 24 * 3600;
                break;
            case 'month':
                $start = $now - 30 * 24 * 3600;
                break;
            case 'quarter':
                $start = $now - 90 * 24 * 3600;
                break;
            case 'year':
                $start = $now - 365 * 24 * 3600;
                break;
            default:
                $start = $now - 30 * 24 * 3600;
        }
        
        return ['a.create_time', '>=', $start];
    }

    /**
     * 获取审批效率统计
     */
    private function getApprovalEfficiencyStats(int $userId, array $timeCondition): array
    {
        // 平均处理时间
        $avgProcessTime = Db::name('workflow_approval_step')
            ->alias('s')
            ->join('workflow_approval a', 's.approval_id = a.id')
            ->where('s.approver_id', $userId)
            ->where('s.status', '>', 0)
            ->where($timeCondition)
            ->avg('TIMESTAMPDIFF(HOUR, FROM_UNIXTIME(s.create_time), FROM_UNIXTIME(s.approve_time))');
        
        // 超时审批数量
        $timeoutCount = Db::name('workflow_approval_step')
            ->alias('s')
            ->join('workflow_approval a', 's.approval_id = a.id')
            ->where('s.approver_id', $userId)
            ->where('s.status', '>', 0)
            ->where($timeCondition)
            ->where('TIMESTAMPDIFF(HOUR, FROM_UNIXTIME(s.create_time), FROM_UNIXTIME(s.approve_time)) > 24')
            ->count();
        
        return [
            'avg_process_hours' => round($avgProcessTime, 2),
            'timeout_count' => $timeoutCount
        ];
    }
}